#ifndef __GRAPHICS_H__
#define __GRAPHICS_H__

#ifdef CLE_NAMESPACE
namespace gui;
#endif

class GColor
{
public:
	GColor(uchar _r = 0, uchar _g = 0, uchar _b = 0, uchar _a = 255)
		:r(_r),g(_g),b(_b),a(_a) {}
	GColor(const GColor& c){ *this = c; }

	long                  toLong()const { return *(long*)&r; }
	uchar                 red() const { return r; }
	uchar                 green() const { return g; }
	uchar                 blue() const { return b; }
	uchar                 alpha() const { return a; }
	void                  setAlpha(uchar alpha){ a = alpha; }

	GColor                invert() const { return GColor(255-r, 255-g,255-b,a); }

	bool operator == (const GColor &c) const{ return toLong() == c.toLong(); }
	GColor& operator = (const GColor &c) { long*p = (long*)&r; *p = c.toLong(); return *this; }
	GColor& operator = (long l) { *(long*)&r = l; return *this; }

private:
	uchar r, g, b, a;
};

typedef void*                 GHGraph;
typedef void*                 GHPen;
typedef void*                 GHBrush;
typedef void*                 GHFont;

class Graphics;
class GFont
{
    
public:
	GFont(Graphics* g = 0) : m_hFont(0),m_pGraphics(g)
        ,m_FontWidth(0),m_FontHeight(0)
        ,m_Ascent(0),m_Decent(0)
    {}
	GFont(const GFont& font){}

    struct FontProperty {
        FontProperty(uchar ps = 12)
            :italic(0),underline(0),deleteline(0),bold(Normal),size(ps) {}
        uchar         italic         : 1;
        uchar         underline      : 1;
        uchar         deleteline     : 1;
        uchar         bold           : 2;
        uchar         size;
        enum          Weight { Normal = 0 , Thin, Heavy };
    };

    int                       getWidth() const/*average char width*/{ return m_FontWidth; }
    int                       getHeight() const { return m_FontHeight; }
    int                       getAscent() const { return m_Ascent; }
    int                       getDecent() const { return m_Decent; }
    GSize                     getTextSize(const GString& str) const; // same with ASCII if not define UNICODE
    GSize                     getCharSize(char ch) const { return getStringSize(&ch, 1); }
    GSize                     getStringSize(const char* pstr, int len)const ; //ASCII char size

    Graphics*                 getGraphics()const { return m_pGraphics;}
    void                      setGraphics(Graphics* pGraph) { m_pGraphics = pGraph; }
    GHFont                    getHandle()const { return m_hFont;}
    void                      setHandle(GHFont hfont) { if (m_hFont != hfont) m_hFont = hfont; }
    bool                      setProperty(const FontProperty& prop);
    void                      getProperty(FontProperty& prop)const;
    void                      setFontName(const GString& name) { m_FontName = name;}
    GString                   getFontName()const { return m_FontName; }

private:
	GHFont                    m_hFont;
	Graphics*                 m_pGraphics;

    short                     m_FontWidth, m_FontHeight;
    short                     m_Ascent, m_Decent;
    GString                   m_FontName;
};

class Graphics
{
    
public:
	struct PenInfo
	{
		enum Style {SOLID = 0, DASH, DOT };
		PenInfo(GColor c = GColor(), int w = 1,Style s = SOLID)
			: width(w), style(s)
		{}

		int             width;
		Style           style;
	};
	struct BrushInfo
	{
		enum Style{ SOLID = 0, HATCHED, IMAGE};
		//enum Hatch { BDIAGONAL = 0, CROSS , DIAGCROSS, FDIAGONAL ,HS_HORIZONTAL ,VERTICAL };

		BrushInfo(GColor c = GColor(), Style s = SOLID)
			: style(s)
		{}

		Style           style;
	};
	
public:
	Graphics(GForm* pForm );
    Graphics(const Graphics& g, GSize size );  // compatible graphics object or memory graphics object
	~Graphics(void);

	GHGraph                getHandle()const { return m_hGraph; }
	void                   setPen(const PenInfo& pen);
	PenInfo                getPen() const { return m_Pen; }
	void                   setBrush(const BrushInfo& Brush);
	BrushInfo              getBrush() const { return m_Brush; }
    GFont&                 getFont() { return m_Font;}
    const GFont&           getFont() const { return m_Font;}
    void                   setFont(const GString& fontName, int pointsize = 12);

	void                   drawLine(const GPoint& start, const GPoint& end, const GColor& color);
	void                   drawRect(const GRect& rc,  const GColor& color);
	void                   fillRect(const GRect& rc,  const GColor& color);
	void                   drawRoundedRect(const GRect& rc, const GColor& border, const GColor& filling);
	void                   drawEllipse(const GRect& rc, const GColor& border, const GColor& filling);
	void                   copy(const GRect& target, const Graphics* graph, const GRect& source = GRect());
    void                   copy(const Graphics* graph);
    void                   drawString(int x, int y, const char* str,int len ,const GColor& strColor = GColor()); //ASCII string
	void                   drawClipString(const GPoint& pos, const char* str,int len, 
                                  const GRect& clipRect,const GColor& strColor = GColor());
    void                   drawText(int x, int y, const GString& str, 
		                          const GColor& strColor = GColor()); //black text as default...  , const GColor& bkColor = GColor(255,255,255,255)
	void                   drawText(const GRect& rc, const GString& str, 
		                          const GColor& strColor = GColor(), const GColor& bkColor = GColor(255,255,255,255));

private:
	GForm*                 m_pForm;
	GHGraph                m_hGraph;
    void*                  m_pPixmap;
	PenInfo                m_Pen;
	BrushInfo              m_Brush;
    GFont                  m_Font;
};







#ifdef CLE_NAMESPACE
}
#endif

#endif
